home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
pcr
/
pcr4_4.lha
/
DIST
/
loading
/
delete_symtab.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-04-03
|
8KB
|
308 lines
/* begincopyright
Copyright (c) 1988 Xerox Corporation. All rights reserved.
Use and copying of this software and preparation of derivative works based
upon this software are permitted. Any distribution of this software or
derivative works must comply with all applicable United States export
control laws. This software is made available AS IS, and Xerox Corporation
makes no warranty about the software, its performance or its conformity to
any specification. Any person obtaining a copy of this software is requested
to send their name and post office or electronic mail address to:
PCR Coordinator
Xerox PARC
3333 Coyote Hill Rd.
Palo Alto, CA
endcopyright */
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <stdio.h>
#include <a.out.h>
#include <errno.h>
/*
* Needed by regexp.
*/
#define INIT register char *regexpp = instring;
#define GETC() (*regexpp++)
#define PEEKC() (*regexpp)
#define UNGETC(c) (--regexpp)
#define RETURN(pointer) return;
#define ERROR(val) regerr(val)
#include <regexp.h>
#ifdef sparc
#define r_symbolnum r_index
#define relocation_info reloc_info_sparc
#endif
#define CLEAN(var) {if (var) {free(var); var = 0;}}
static int file_length;/* length of input file in bytes */
static FILE *file; /* input file */
struct exec header;
struct nlist *symtab;
caddr_t stringtab;
int num_symbols;
long string_len;
unsigned long num_reloc_data_items, num_reloc_text_items;
struct relocation_info *data_reloctab, *text_reloctab;/* relocation table */
unsigned long num_reloc_data_items_kept, num_reloc_text_items_kept;
#define INCN 100000
static int maxn = 0;
static int nextn = 0;
static int *saven = 0;
#define MAXCOMPILEDREGSIZE 1000
char expbuf[MAXCOMPILEDREGSIZE];
char *current_file;
compare_n(a, b)
int *a, *b;
{
return(*a - *b);
}
/*
* Main program for 'delete_symtab'.
*/
main(argc, argv)
char **argv;
{
/* process arguments */
if (argc < 3) {
printf("Usage: %s regexp filename[s].\n\tRemoves any symbols which match the regular expression.\n", argv[0]);
exit(1);
};
argc--; argv++;
compile(*argv, expbuf, &expbuf[MAXCOMPILEDREGSIZE], '\0');
for (; --argc > 0;) {
simplify_file(*++argv);
}
exit(0);
}
simplify_file(onefilename)
char *onefilename;
{
int i, n_i;
printf("Deleting syms in %s.\n", onefilename);
current_file = onefilename; /* for error messages */
/*
* Initialize.
*/
maxn = 0;
nextn = 0;
CLEAN(saven);
CLEAN(symtab);
CLEAN(data_reloctab);
CLEAN(text_reloctab);
CLEAN(stringtab);
/*
* Open the file: don't return if unopened.
*/
open_file(onefilename);
/*
* Look for symbols that don't match the regexp. Remember them.
*/
for(i=0; i < num_symbols; i++ ) {
if ( ! step(symtab[i].n_un.n_strx + stringtab, expbuf)) {
remember_n(i);
} else {
i = i; /* someplace to put a breakpoint */
}
}
/*
* Start point for writing new file information.
*/
fseek(file, N_TRELOFF(header), 0);
/*
* Write out text relocation information, adjusted to new symbol locations.
*/
num_reloc_text_items_kept = 0;
for (i=0; i < num_reloc_text_items; i++) {
if (text_reloctab[i].r_extern && (n_i = n_p(text_reloctab[i].r_symbolnum)) == -1) {
i = i; /* a place to put breakpoints */
} else {
if (text_reloctab[i].r_extern) {
text_reloctab[i].r_symbolnum = n_i;
}
fwrite(&text_reloctab[i], sizeof(struct relocation_info), 1, file);
num_reloc_text_items_kept += 1;
}
}
/*
* Write out data relocation information that points to saved symbols only.
*/
num_reloc_data_items_kept = 0;
for (i=0; i < num_reloc_data_items; i++) {
if (data_reloctab[i].r_extern && (n_i = n_p(data_reloctab[i].r_symbolnum)) == -1) {
i = i; /* a place to put breakpoints */
} else {
if (data_reloctab[i].r_extern) {
data_reloctab[i].r_symbolnum = n_i;
}
fwrite(&data_reloctab[i], sizeof(struct relocation_info), 1, file);
num_reloc_data_items_kept += 1;
}
}
/*
* Write out symbols that did not have nstabs bit set.
* by copying them in place on top of other symbols.
*/
for(i=0; i < nextn; i++ ) {
fwrite(&symtab[saven[i]], sizeof(struct nlist), 1, file);
}
/*
* Write out the same old stringtab (now in a new place in the file).
* (Someday the stringtab could also be shrunk.)
*/
fwrite(stringtab, string_len, 1, file);
/*
* Update the header, and write it out.
*/
header.a_syms = sizeof(struct nlist)*nextn;
header.a_drsize = sizeof(struct relocation_info)*num_reloc_data_items_kept;
header.a_trsize = sizeof(struct relocation_info)*num_reloc_text_items_kept;
fseek(file, (long)0, 0);
fwrite(&header, sizeof(struct exec), 1, file);
fflush(file);
ftruncate(fileno(file), file_length - (num_symbols-nextn)*sizeof(struct nlist));
/* done with this file */
fclose(file);
}
open_file(filename)
char *filename;
{
struct stat the_stat_buffer;
/*
* Open the file: don't return if unopened.
*/
if ((file = fopen(filename, "r+")) == NULL) {
char temp[128];
sprintf(temp, "Cannot open file '%s'.", filename);
error(temp); /* never returns */
}
/* get the file size */
fstat(fileno(file), &the_stat_buffer);
file_length = the_stat_buffer.st_size;
fseek(file, (long)0, 0);
fread (&header, sizeof(struct exec), 1, file);
if (N_BADMAG(header)) {
error("Bad magic number."); /* never returns */
}
num_reloc_text_items = (header.a_trsize / sizeof (struct relocation_info));
num_reloc_data_items = (header.a_drsize / sizeof (struct relocation_info));
if (num_reloc_text_items > 0) {
text_reloctab = (struct relocation_info *)malloc(sizeof(struct relocation_info)*num_reloc_text_items);
fseek(file, N_TRELOFF(header), 0);
fread (text_reloctab, sizeof (struct relocation_info), num_reloc_text_items, file);
}
if (num_reloc_data_items > 0) {
data_reloctab = (struct relocation_info *)malloc(sizeof(struct relocation_info)*num_reloc_data_items);
fseek(file, N_DRELOFF(header), 0);
fread (data_reloctab, sizeof (struct relocation_info), num_reloc_data_items, file);
}
/*
* Read in the symbol table
*/
num_symbols = header.a_syms / (sizeof (struct nlist));
if (num_symbols <= 0) {
error("No symbol table."); /* never returns */
}
symtab= (struct nlist *) malloc (header.a_syms);
fseek(file, N_SYMOFF(header), 0);
fread (symtab, sizeof (struct nlist), num_symbols, file);
/*
* Read in the string table
*/
{
string_len = (file_length - N_STROFF(header));
if (string_len <= 0) {
error("No string table."); /* never returns */
}
stringtab = (caddr_t) malloc (string_len);
fseek(file, N_STROFF(header), 0);
fread (stringtab, 1, string_len, file);
}
}
error(s)
char *s;
{
printf("simplify_symtab error: %s, in file '%s'\n", s, current_file);
exit(1);
}
remember_n(n)
int n;
{
if (nextn >= maxn) {
/* need more storage */
maxn += INCN;
if (saven) {
saven = (int *)realloc(saven, maxn*sizeof(int));
} else {
saven = (int *)malloc(maxn*sizeof(int));
}
}
saven[nextn++] = n;
}
n_p(n)
int n;
{
int *retval;
retval = (int *)bsearch(&n, saven, nextn, sizeof(int), compare_n);
if (retval == 0) {
return -1;
} else {
return ((long)retval - (long)saven)/sizeof(int);
}
}
regerr(val)
{
char *s;
printf("delete_symtab: Error in regular expression.");
switch(val) {
case 11: s = "Range endpoint too large."; break;
case 16: s = "Bad number."; break;
case 25: s = "``\ digit'' out of range."; break;
case 36: s = "Illegal or missing delimiter."; break;
case 41: s = "No remembered search string."; break;
case 42: s = "\( \) imbalance."; break;
case 43: s = "Too many \(."; break;
case 44: s = "More than 2 numbers given in \{ \}."; break;
case 45: s = "} expected after \."; break;
case 46: s = "First number exceeds second in \{ \}."; break;
case 49: s = "[] imbalance."; break;
case 50: s = "Regular expression too long."; break;
}
exit(1);
}